#!/bin/bash

# 物业保洁系统一键部署脚本
# 支持开发、测试、生产环境部署

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 默认配置
ENVIRONMENT=${1:-dev}
BACKUP_DIR="/backup/property-cleaning"
LOG_FILE="/tmp/deploy-$(date +%Y%m%d_%H%M%S).log"

# 帮助信息
show_help() {
    echo "用法: $0 [环境] [选项]"
    echo ""
    echo "环境:"
    echo "  dev     开发环境部署"
    echo "  test    测试环境部署" 
    echo "  prod    生产环境部署"
    echo ""
    echo "选项:"
    echo "  --help  显示帮助信息"
    echo "  --backup 部署前创建备份"
    echo "  --skip-tests 跳过测试"
    echo ""
    echo "示例:"
    echo "  $0 dev"
    echo "  $0 prod --backup"
}

# 日志函数
log() {
    echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] $1${NC}" | tee -a "$LOG_FILE"
}

error() {
    echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1${NC}" | tee -a "$LOG_FILE"
}

warning() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARNING: $1${NC}" | tee -a "$LOG_FILE"
}

# 检查环境
check_environment() {
    log "检查环境: $ENVIRONMENT"
    
    # 检查Docker
    if ! command -v docker &> /dev/null; then
        error "Docker未安装"
        exit 1
    fi
    
    # 检查Docker Compose
    if ! command -v docker-compose &> /dev/null; then
        error "Docker Compose未安装"
        exit 1
    fi
    
    # 检查必要目录
    if [[ ! -d "backend" || ! -d "frontend" ]]; then
        error "缺少必要目录，请在项目根目录运行"
        exit 1
    fi
}

# 创建备份
create_backup() {
    if [[ "$BACKUP" == "true" ]]; then
        log "创建备份..."
        mkdir -p "$BACKUP_DIR"
        
        # 数据库备份
        if docker ps | grep -q "property-mysql"; then
            docker exec property-mysql mysqldump -u root -proot123 property_cleaning > \
                "$BACKUP_DIR/db-$(date +%Y%m%d_%H%M%S).sql"
            log "数据库备份完成"
        fi
        
        # 文件备份
        if [[ -d "/opt/property-cleaning/uploads" ]]; then
            tar -czf "$BACKUP_DIR/files-$(date +%Y%m%d_%H%M%S).tar.gz" /opt/property-cleaning/uploads
            log "文件备份完成"
        fi
    fi
}

# 开发环境部署
deploy_dev() {
    log "开始部署开发环境..."
    
    # 启动数据库
    log "启动MySQL..."
    docker run -d --name property-mysql-dev \
        -e MYSQL_ROOT_PASSWORD=root123 \
        -e MYSQL_DATABASE=property_cleaning \
        -e MYSQL_USER=dev_user \
        -e MYSQL_PASSWORD=dev_pass \
        -p 3306:3306 \
        -v mysql_dev_data:/var/lib/mysql \
        mysql:8.0 || warning "MySQL容器已存在"
    
    # 启动Redis
    log "启动Redis..."
    docker run -d --name property-redis-dev \
        -p 6379:6379 \
        -v redis_dev_data:/data \
        redis:7-alpine || warning "Redis容器已存在"
    
    # 等待数据库启动
    log "等待数据库启动..."
    sleep 10
    
    # 初始化数据库
    if [[ -f "database/schema.sql" ]]; then
        log "初始化数据库..."
        docker exec -i property-mysql-dev mysql -u root -proot123 property_cleaning < database/schema.sql || warning "数据库已初始化"
    fi
    
    # 启动后端
    log "构建并启动后端..."
    cd backend
    mvn clean package -DskipTests
    java -jar -Dspring.profiles.active=dev target/property-cleaning-backend-1.0.0.jar &
    BACKEND_PID=$!
    cd ..
    
    # 启动前端
    log "构建并启动前端..."
    cd frontend
    npm install
    npm run dev &
    FRONTEND_PID=$!
    cd ..
    
    log "开发环境部署完成！"
    log "前端: http://localhost:3000"
    log "后端: http://localhost:8080"
    log "MySQL: localhost:3306"
    log "Redis: localhost:6379"
    
    # 保存PID
    echo $BACKEND_PID > /tmp/property-backend-dev.pid
    echo $FRONTEND_PID > /tmp/property-frontend-dev.pid
}

# 测试环境部署
deploy_test() {
    log "开始部署测试环境..."
    
    # 使用Docker Compose
    if [[ -f "docker-compose.test.yml" ]]; then
        docker-compose -f docker-compose.test.yml down || true
        docker-compose -f docker-compose.test.yml up -d --build
    else
        # 创建测试配置
        cat > docker-compose.test.yml << EOF
version: '3.8'
services:
  mysql-test:
    image: mysql:8.0
    container_name: property-mysql-test
    environment:
      MYSQL_ROOT_PASSWORD: test_root_2024
      MYSQL_DATABASE: property_cleaning_test
      MYSQL_USER: test_user
      MYSQL_PASSWORD: test_pass_2024
    ports:
      - "3307:3306"
    volumes:
      - mysql_test_data:/var/lib/mysql
      - ./database/schema.sql:/docker-entrypoint-initdb.d/schema.sql

  redis-test:
    image: redis:7-alpine
    container_name: property-redis-test
    ports:
      - "6380:6379"

  backend-test:
    build: ./backend
    container_name: property-backend-test
    depends_on:
      - mysql-test
      - redis-test
    environment:
      SPRING_PROFILES_ACTIVE: test
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql-test:3306/property_cleaning_test
      SPRING_DATASOURCE_USERNAME: test_user
      SPRING_DATASOURCE_PASSWORD: test_pass_2024
    ports:
      - "8081:8080"

  frontend-test:
    build: ./frontend
    container_name: property-frontend-test
    depends_on:
      - backend-test
    ports:
      - "3001:80"
    environment:
      - VITE_API_BASE_URL=http://localhost:8081

volumes:
  mysql_test_data:
EOF
        docker-compose -f docker-compose.test.yml up -d --build
    fi
    
    log "测试环境部署完成！"
    log "前端: http://localhost:3001"
    log "后端: http://localhost:8081"
    log "MySQL: localhost:3307"
    log "Redis: localhost:6380"
}

# 生产环境部署
deploy_prod() {
    log "开始部署生产环境..."
    
    # 创建备份
    create_backup
    
    # 生产环境检查
    read -p "确认部署到生产环境? (y/N): " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        log "取消生产环境部署"
        exit 0
    fi
    
    # 使用生产配置
    if [[ -f "docker-compose.prod.yml" ]]; then
        log "使用生产配置部署..."
        docker-compose -f docker-compose.prod.yml down || true
        docker-compose -f docker-compose.prod.yml up -d --build
    else
        # 创建生产配置
        cat > docker-compose.prod.yml << EOF
version: '3.8'
services:
  mysql-prod:
    image: mysql:8.0
    container_name: property-mysql-prod
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:-prod_root_secure_2024}
      MYSQL_DATABASE: property_cleaning_prod
      MYSQL_USER: ${DB_USER:-prod_user}
      MYSQL_PASSWORD: ${DB_PASSWORD:-prod_pass_secure_2024}
    ports:
      - "3306:3306"
    volumes:
      - mysql_prod_data:/var/lib/mysql
      - ./database/schema.sql:/docker-entrypoint-initdb.d/schema.sql
    command: --default-authentication-plugin=mysql_native_password

  redis-prod:
    image: redis:7-alpine
    container_name: property-redis-prod
    ports:
      - "6379:6379"
    volumes:
      - redis_prod_data:/data
    command: redis-server --requirepass ${REDIS_PASSWORD:-prod_redis_2024}

  backend-prod:
    build: ./backend
    container_name: property-backend-prod
    depends_on:
      - mysql-prod
      - redis-prod
    environment:
      SPRING_PROFILES_ACTIVE: prod
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql-prod:3306/property_cleaning_prod
      SPRING_DATASOURCE_USERNAME: ${DB_USER:-prod_user}
      SPRING_DATASOURCE_PASSWORD: ${DB_PASSWORD:-prod_pass_secure_2024}
    ports:
      - "8080:8080"
    restart: unless-stopped

  frontend-prod:
    build: ./frontend
    container_name: property-frontend-prod
    depends_on:
      - backend-prod
    ports:
      - "80:80"
    restart: unless-stopped
    environment:
      - VITE_API_BASE_URL=http://localhost:8080

volumes:
  mysql_prod_data:
  redis_prod_data:
EOF
        docker-compose -f docker-compose.prod.yml up -d --build
    fi
    
    log "生产环境部署完成！"
    log "前端: http://localhost"
    log "后端: http://localhost:8080"
    log "MySQL: localhost:3306"
    log "Redis: localhost:6379"
}

# 健康检查
health_check() {
    log "执行健康检查..."
    
    # 检查MySQL
    if docker ps | grep -q "property-mysql"; then
        log "✓ MySQL服务运行正常"
    else
        error "MySQL服务未运行"
    fi
    
    # 检查Redis
    if docker ps | grep -q "property-redis"; then
        log "✓ Redis服务运行正常"
    else
        error "Redis服务未运行"
    fi
    
    # 检查后端
    if curl -s http://localhost:8080/actuator/health > /dev/null; then
        log "✓ 后端服务运行正常"
    else
        error "后端服务未运行"
    fi
    
    # 检查前端
    if curl -s http://localhost:3000 > /dev/null; then
        log "✓ 前端服务运行正常"
    else
        error "前端服务未运行"
    fi
}

# 停止服务
stop_services() {
    log "停止服务..."
    
    case $ENVIRONMENT in
        dev)
            # 停止Java进程
            if [[ -f /tmp/property-backend-dev.pid ]]; then
                kill $(cat /tmp/property-backend-dev.pid) 2>/dev/null || true
                rm /tmp/property-backend-dev.pid
            fi
            if [[ -f /tmp/property-frontend-dev.pid ]]; then
                kill $(cat /tmp/property-frontend-dev.pid) 2>/dev/null || true
                rm /tmp/property-frontend-dev.pid
            fi
            
            # 停止Docker容器
            docker stop property-mysql-dev property-redis-dev 2>/dev/null || true
            docker rm property-mysql-dev property-redis-dev 2>/dev/null || true
            ;;
        test)
            docker-compose -f docker-compose.test.yml down 2>/dev/null || true
            ;;
        prod)
            docker-compose -f docker-compose.prod.yml down 2>/dev/null || true
            ;;
    esac
    
    log "服务已停止"
}

# 显示状态
show_status() {
    log "当前服务状态:"
    
    case $ENVIRONMENT in
        dev)
            docker ps | grep -E "(mysql|redis)" | grep dev || echo "无运行中的容器"
            ;;
        test)
            docker-compose -f docker-compose.test.yml ps
            ;;
        prod)
            docker-compose -f docker-compose.prod.yml ps
            ;;
    esac
}

# 主函数
main() {
    # 解析参数
    while [[ $# -gt 0 ]]; do
        case $1 in
            --help)
                show_help
                exit 0
                ;;
            --backup)
                BACKUP=true
                shift
                ;;
            --skip-tests)
                SKIP_TESTS=true
                shift
                ;;
            --stop)
                stop_services
                exit 0
                ;;
            --status)
                show_status
                exit 0
                ;;
            --health)
                health_check
                exit 0
                ;;
            dev|test|prod)
                ENVIRONMENT=$1
                shift
                ;;
            *)
                error "未知参数: $1"
                show_help
                exit 1
                ;;
        esac
    done
    
    log "开始部署到 $ENVIRONMENT 环境"
    
    # 检查环境
    check_environment
    
    # 根据环境执行部署
    case $ENVIRONMENT in
        dev)
            deploy_dev
            ;;
        test)
            deploy_test
            ;;
        prod)
            deploy_prod
            ;;
        *)
            error "未知环境: $ENVIRONMENT"
            exit 1
            ;;
    esac
    
    # 健康检查
    sleep 10
    health_check
    
    log "部署完成！"
}

# 执行主函数
main "$@"